package Project2.cs342.project1.mathNotebook.data;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import Project2.cs342.project1.mathNotebook.notebook.NotebookEntry;

public class XMLNotebookReader implements NotebookReader {
    	private InputStream inputStream;
    
    	public XMLNotebookReader(InputStream inputStream) {
    	    this.inputStream = inputStream;
    	}
    
    	/**
    	 * Reads NotebookEntry objects from XML.
    	 */
	@Override
	public List<NotebookEntry> getAll() {
		List<NotebookEntry> results = new ArrayList<NotebookEntry>();
		NotebookEntry entry = null;
		
		Parser parser = new Parser();
		
		XMLInputFactory factory = XMLInputFactory.newInstance();
		try {
			XMLStreamReader reader = factory.createXMLStreamReader(inputStream);
			while (reader.hasNext()) {
				int eventType = reader.getEventType();
				switch (eventType) {
				case XMLStreamConstants.START_ELEMENT:
					if (reader.getLocalName().equals("formula")) {
						entry = new NotebookEntry();
						int attributeCount = reader.getAttributeCount();
						for (int i = 0; i < attributeCount; i++) {
							if (reader.getAttributeLocalName(i).equals("equation")) {
								entry.functionString = reader.getAttributeValue(i);
								try {
									entry.function = parser.getExpression(entry.functionString);
								} catch (Exception e) {}
							}
						}
						results.add(entry);
					} else if (reader.getLocalName().equals("tangent")) {
					    int attributeCount = reader.getAttributeCount();
					    for (int i=0; i < attributeCount; i++) {
						if (reader.getAttributeLocalName(i).equals("point")) {
						    entry.tangentPoints.add(Double.parseDouble(reader.getAttributeValue(i)));
						}
					    }
					}
					break;
				}

				reader.next();
			}
		} catch (XMLStreamException e) {
			// Present the user with an empty file in case of errors
		}

		return results;
	}

	/**
	 * Closes the inputStream
	 * @author Jared Schlicht
	 */
	@Override
	public void close() {
	    try {
		this.inputStream.close();
	    } catch (Exception ex) {}
	}
}
